This tutorial explains about contentnegotiatingviewresolver in spring mvc using annotations and java configs. Here we will have a single controller that can produce responses in different data format such as json, html or xml etc. based on the request url without creating any extra layers. We only require to have contentnegotiatingviewresolver configurations that will do this for us. Now, let us implement this with the following spring mvc contentnegotiatingviewresolver example. In this example we will have responses in json, xml and html based on the request file name.
What is Contentnegotiating Viewresolver
ContentNegotiating ViewResolver is an implementation of ViewResolver, that resolves a view based on the request file name or accept header. With the help of ContentNegotiatingViewResolver, a single spring controller method can produce http response in different data formats such as xml, json, excel, pdf etc. of your choice.
The highest priority for contentnegotiatingviewresolver has the file extension which is used if available in the request and all our http requests will have file extensions for JSON and xml.
Next, the contentnegotiatingviewresolver looks for a request parameter that identifies the view. If that is also not available, it uses the Java Activation Framework to determine the Content-Type. If these all fails, it uses the the HTTP Accept header.
Why Contentnegotiating Viewresolver Required
The controller class used in spring web application mostly return ModelAndViews or view name. But when it comes to only data represenation that could be xml, json or excel then contentnegotiatingviewresolver comes int picture. Without introducing any extra layer or extra code to meet the data representation requirement, we can achieve this by using contentnegotiatingviewresolver.
Now let us dive into its implementation using spring mvc.
Project Structure
Here all the spring config classes are inside the package com.devglan.config and all the static components inside webapp/ui. The jsp pages are defined inside WEB-INF/jsp.
Maven Dependencies
pom.xml
The dependencies here are usual dependencies for a spring mvc application.
spring-webmvc - provides core HTTP integration including filters. Including this dependency automatically includes spring-web.
javax.servlet-api - Provides all the dependency related to servlet api.
jstl - Provides all the dependencies for jstl.
maven-war-plugin - This is required to build war package by maven as we are excluding web.xml based configurations.
<modelVersion>4.0.0</modelVersion> <groupId>com.devglan</groupId> <artifactId>spring-mvc-example</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <spring.version>4.3.7.RELEASE</spring.version> <jstl.version>1.2</jstl.version> <servlet.version>3.0.1</servlet.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.7.4</version> </dependency> </dependencies> <build> <finalName>spring-mvc-content-negotiation-example</finalName> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.4</version> <configuration> <warName>spring-mvc</warName> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </pluginManagement> </build>
Other Interesting Posts Spring Mvc Annotation Example Spring JMS ActiveMq Integration Example Spring MVC AngularJs Integration Example Spring Hibernate Integration Example Writing Junit Tests in Spring 4 MVC Spring Ehcache Cacheable Example Spring 5 Features and Enhancements
Defining Spring Controller
Following is the controller class which is mapped for /users. It is a normal controller class that returns ModelAndView and based on the requested url the resolver will be identified and corresponding response will be generated.
UserController.java
package com.devglan.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import com.devglan.model.UserDetails; import com.devglan.service.UserService; @Controller public class UserController { @Autowired private UserService userService; @RequestMapping(value = "/users", method = RequestMethod.GET) public ModelAndView userDetails() { ModelAndView modelAndView = new ModelAndView(); ListuserDetails = userService.getUserDetails(); modelAndView.addObject("users", userDetails); modelAndView.setViewName("userDetails"); return modelAndView; } }
Defining Spring MVC Service
Following is the service class that generates user details and returns to the controller.
UserServiceImpl.java
package com.devglan.service.impl; import java.util.Arrays; import java.util.List; import org.springframework.stereotype.Service; import com.devglan.model.UserDetails; import com.devglan.service.UserService; @Service public class UserServiceImpl implements UserService { public ListgetUserDetails() { UserDetails ud1 = new UserDetails(); ud1.setEmail("john@example.com"); ud1.setFirstName("John"); ud1.setLastName("Doe"); UserDetails ud2 = new UserDetails(); ud2.setEmail("vicky@gmail.com"); ud2.setFirstName("vicky"); ud2.setLastName("Ray"); UserDetails ud3 = new UserDetails(); ud3.setEmail("abc@yahoo.co.in"); ud3.setFirstName("abc"); ud3.setLastName("greg"); UserDetails ud4 = new UserDetails(); ud4.setFirstName("xyz"); ud4.setEmail("xyz@gmail.com"); ud4.setLastName("Bard"); return Arrays.asList(ud1, ud2, ud3, ud4); } }
Let us define the POJO now.
UserDetails.java
package com.devglan.model; public class UserDetails { private String firstName; private String lastName; private String email; //getters and setters goes here }
Configuring ServletContex in Spring MVC
This implementaion will be automatically detected by SpringServletContainerInitializer which itself is bootstrapped automatically by any Servlet 3.0 container such as tomcat.
AppInitializer.java
package com.devglan.config; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; public class AppInitializer implements WebApplicationInitializer { public void onStartup(ServletContext container) throws ServletException { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); ctx.register(WebConfig.class); ctx.setServletContext(container); ServletRegistration.Dynamic servlet = container.addServlet("dispatcher", new DispatcherServlet(ctx)); servlet.setLoadOnStartup(1); servlet.addMapping("/"); } }
Configuring ContentNegotiating ViewResolver in Spring MVC
ContentNegotiationConfigurer creates a ContentNegotiationManagernand configures it with one or more ContentNegotiationStrategy instances.
configureViewResolvers() will register different view resolvers. Here we are registering view resolvers for HTML, xml and JSON. Hence, when a request is made with url ending .json, a JSON view will be rendered and similarly xml for view for url ending with .xml
WebConfig.java
@Configuration @EnableWebMvc @ComponentScan(basePackages = "com.devglan") public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer .defaultContentType(MediaType.TEXT_HTML) .ignoreAcceptHeader(true); } @Override public void configureViewResolvers(ViewResolverRegistry registry) { registry.jsp("/WEB-INF/jsp/", ".jsp").viewClass(JstlView.class); registry.enableContentNegotiation( new MappingJackson2XmlView(), new MappingJackson2JsonView() ); } @Override public void addResourceHandlers(final ResourceHandlerRegistry registry) { registry.addResourceHandler("/js/**").addResourceLocations("/ui/js/"); registry.addResourceHandler("/css/**").addResourceLocations("/ui/css/"); } }
Client Side Implementation
Following is the jsp page that will be rendered when no requests with any file extension.
userDetails.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title> Spring Boot Example</title> <link href="css/bootstrap.min.css" rel="stylesheet"> <script src="js/jquery-2.2.1.min.js"></script> <script src="js/bootstrap.min.js"></script> </head> <body> <div> <div class="container" style="margin:50px"> <div class="row text-center"><strong> User Details</strong></div> <div class="row" style="border:1px solid green;padding:10px"> <div class="col-md-3 text-center"><strong>First Name</strong></div> <div class="col-md-3 text-center"><strong>Last Name</strong></div> <div class="col-md-3 text-center"><strong>Email</strong></div> </div> <c:forEach var="user" items="${users}"> <div class="row" style="border:1px solid green;padding:10px"> <div class="col-md-3 text-center">${user.firstName}</div> <div class="col-md-3 text-center" >${user.lastName}</div> <div class="col-md-3 text-center">${user.email}</div> </div> </c:forEach> </div> </div> </body> </html>
Run Spring MVC Application
1. Deploy the application to tomcat.
2. Hit the url as http://localhost:8080/spring-mvc-content-negotiation-example/users.json
and you can see following result.
2. Hit the url as http://localhost:8080/spring-mvc-content-negotiation-example/users.xml
and you can see following result.
2. Hit the url as http://localhost:8080/spring-mvc-content-negotiation-example/users
and you can see following result.
Conclusion
I hope this article served you that you were looking for. If you have anything that you want to add or share then please share it below in the comment section.